const PEDDING = "PEDDING";
const RESOLVED = "RESOLVED";
const REJECTED = "REJECTED";
function resolvePromise(promise2, x, resolve, reject) {
  // console.log(promise2,'promise2~~~');
  if (promise2 === x) {
    return reject(
      new TypeError("Chaining cycle detected for promise #<Promise>")
    );
  }
  let called;
  if ((typeof x === "object" && x != null) || typeof x === "function") {
    try {
      // try catch 目的是为了防止x.then报错
      let then = x.then;
      if (typeof then === "function") {
        then.call(
          x,
          function fn2(y) {
            if (called) return;
            called = true;

            resolvePromise(promise2, y, resolve, reject);
          },
          (e) => {
            if (called) return;
            called = true;
            reject(e);
          }
        );
      } else {
        resolve(x);
      }
    } catch (e) {
      if (called) return;
      called = true;
      reject(e);
    }
  } else {
    resolve(x);
  }
}
console.log("MY");
class Promise {
  constructor(executor) {
    this.status = PEDDING; // 默认是pedding状态
    this.reason = undefined;
    this.value = undefined;
    this.resolveFn = []; //存储成功的fn
    this.rejectedFn = []; //存储失败的fn
    let resolve = (data) => {
      if (this.status === PEDDING) {
        this.value = data;
        this.status = RESOLVED;

        this.resolveFn.forEach((fn) => fn());
      }
    };
    let reject = (data) => {
      if (this.status === PEDDING) {
        this.reason = data;
        this.status = REJECTED;
        this.rejectedFn.forEach((fn) => fn());
      }
    };
    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }
  then(onfulfilled, onrejected) {
    onfulfilled = onfulfilled ? onfulfilled : (v) => v;
    onrejected = onrejected
      ? onrejected
      : (e) => {
          throw e;
        };
    const promise2 = new Promise((resolve, reject) => {
      if (this.status === RESOLVED) {
        try {
          setTimeout(() => {
            const x = onfulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          }, 0);
        } catch (e) {
          reject(e);
        }
      }
      if (this.status === REJECTED) {
        // try catch 包裹的原因
        try {
          setTimeout(() => {
            const x = onrejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          }, 0);
        } catch (e) {
          reject(e);
        }
      }
      if (this.status === PEDDING) {
        this.resolveFn.push(() => {
          // todo
          setTimeout(() => {
            try {
              let x = onfulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0);
        });
        this.rejectedFn.push(() => {
          // todo
          setTimeout(() => {
            try {
              let x = onrejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0);
        });
      }
    });
    return promise2;
  }
}
module.exports = Promise;
